/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ddbserver.server;

import ddbserver.DDBServerView;
import ddbserver.common.ExceptionHandler;
import ddbserver.common.ObjectServer;
import ddbserver.common.ResultType;
import ddbserver.common.SQLResult;
import ddbserver.connections.SiteManager;
import ddbserver.connections.SocketConnector;
import ddbserver.common.Site;
import ddbserver.connections.ObjectManager;
import ddbserver.constant.Constant;
import java.io.File;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Roar
 */
public class ClientUtil extends CommonUtil {

    PaserUtil paser;
    DatabaseUtil dbUtil;

    public ClientUtil(SocketConnector socketConnector, DDBServerView mainWindow, String name) {
        super(socketConnector, mainWindow, name);
        this.paser = new PaserUtil(new DatabaseUtil(mainWindow.getMySQLConnector()), name);
        this.dbUtil = new DatabaseUtil(mainWindow.getMySQLConnector());
    }

    private void clientEcho() {
        socketConnector.send(name);
        String site = socketConnector.read();
        SiteManager.getInstance().addSite(site);
        SiteManager.getInstance().getSite(site).setConnected(true);
        DDBServerView.getInstance().refeshServerList();
    }

    private void clientSync() {
        List<Site> beforesync = SiteManager.getInstance().getConnectedSite();
        List<String> newsite = new ArrayList<String>();
        int num = Integer.parseInt(socketConnector.read());
        for (int i = 0; i < num; i++) {
            String line = socketConnector.read();
            if (SiteManager.getInstance().getSite(line) == null || SiteManager.getInstance().getSite(line).isConnected() == false) {
                newsite.add(line);
            }
        }
        socketConnector.send("" + beforesync.size());
        for (Site site : beforesync) {
            socketConnector.send(site.toString());
        }
        for (String st : newsite) {
            SiteManager.getInstance().addSite(st);
            SiteManager.getInstance().getSite(st).setConnected(true);
        }
        for (Site site : beforesync) {
            site.newSession();
            site.send("client");
            site.send("active");
            site.send("" + newsite.size());
            for (String string : newsite) {
                site.send(string);
            }
        }
        DDBServerView.getInstance().refeshServerList();
    }

    private void clientActive() {
        int num = Integer.parseInt(socketConnector.read());
        for (int i = 0; i < num; i++) {
            String site = socketConnector.read();
            SiteManager.getInstance().addSite(site);
            SiteManager.getInstance().getSite(site).setConnected(true);
        }
        DDBServerView.getInstance().refeshServerList();

    }

    private void clientReciveFile() {
        String siteName = socketConnector.read();
        String fileType = socketConnector.read();
        String dataPath = new String();
        if (fileType.equals(Constant.DDB_INITIAL_PROPERTIES_FILE)) {
            dataPath = "./";
        } else if (fileType.equals(Constant.DDB_INITIAL_DATA_FILE)) {
            dataPath = "./Data/";
        }
        String fileName = socketConnector.read();
        if (!(new File(dataPath)).exists()) {
            (new File(dataPath)).mkdirs();
        }

        Random rand = new Random();
        int filePort = 10000 + rand.nextInt(10000);
        for (int i = 0; i < 3; i++) {
            try {
                ServerSocket serverSocket = new ServerSocket(filePort, 0, InetAddress.getByName(SiteManager.getInstance().getMyip()));
                socketConnector.send("" + filePort);
                SocketConnector fileConnector = new SocketConnector(serverSocket.accept(), Constant.DDB_SOCKET_FILE);
                fileConnector.receiveFile(dataPath + fileName);
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
            filePort = 10000 + rand.nextInt(10001);
        }
    }

    public void clientSendObjcet() {
        String objcetKey = socketConnector.read();
        Random rand = new Random();
        int objectPort = 10000 + rand.nextInt(10000);
        Object objectToSend = ObjectManager.getInstance().getAndRemoveObject(objcetKey);
        for (int i = 0; i < 3; i++) {
            try {
                ServerSocket serverSocket = new ServerSocket(objectPort, 0, InetAddress.getByName(SiteManager.getInstance().getMyip()));
                socketConnector.send("" + objectPort);
                SocketConnector objectConnector = new SocketConnector(serverSocket.accept(), Constant.DDB_SOCKET_OBJECT);
                objectConnector.sendObject(objectToSend);
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
            objectPort = 10000 + rand.nextInt(10001);
        }
    }

    public void clientReceiveObject() {
        String sqlType = socketConnector.read();
        SQLResult sqlResult;
        Random rand = new Random();
        int objectPort = 10000 + rand.nextInt(10000);
        if (sqlType.equals(Constant.REMOTE_COMMAND_NONRESULT)) {
            String sql = socketConnector.read();
            sqlResult = new SQLResult(name, sql, sqlType);
            dbUtil.execute(sqlResult);
            mainWindow.setText("create table successfully: \n\r" + sql);
        } else if (sqlType.equals(Constant.REMOTE_COMMAND_RESULTE)) {
            try {
                ServerSocket serverSocket = new ServerSocket(objectPort, 0,
                        InetAddress.getByName(SiteManager.getInstance().getMyip()));
                SocketConnector objectConnector = new SocketConnector(serverSocket.accept(),
                        Constant.DDB_SOCKET_OBJECT);
                sqlResult = (SQLResult) objectConnector.receiveObject();
                dbUtil.execute(sqlResult);
            } catch (Exception e) {
                ExceptionHandler.handleExcptin(e);
            }
        }
    }

    public void clientReceiveSQLReturnResult() {
        Site site = SiteManager.getInstance().getSiteByName(socketConnector.read());
        String port = socketConnector.read();
        try {
            SQLResult sqlResult = (SQLResult)site.reciveObject(Integer.parseInt(port));
            ResultSet rs = dbUtil.getQueryResult(sqlResult.getSql());
            ResultType rt = new ResultType();
            rt.setResutlVector(rs);
            sqlResult.setResult(rt);
            Random rand = new Random();
            int objectPort = 10000 + rand.nextInt(10000);
            socketConnector.send("" + objectPort);
            new ObjectServer(objectPort, sqlResult);
        } catch (Exception e) {
            ExceptionHandler.handleExcptin(e);
        }


    }

    public void clientReceiveSQLResult() {
        String key = socketConnector.read();
        String siteName = socketConnector.read();
        Site site = SiteManager.getInstance().getSiteByName(siteName);
        SQLResult sqlResulte = (SQLResult)site.reciveObject(key);
        dbUtil.execute(sqlResulte);
    }
    
    public void clientDeactive() {
        String site = socketConnector.read();
        SiteManager.getInstance().getSite(site).setConnected(false);
        DDBServerView.getInstance().refeshServerList();
    }

    public void clientDisconnect() {
        List<Site> sites = SiteManager.getInstance().getConnectedSite();
        for (Site site : sites) {
            site.setConnected(false);
        }
        SiteManager.getInstance().getSite(SiteManager.getInstance().getMyself()).setConnected(true);
        DDBServerView.getInstance().refeshServerList();
    }

    public void run() {
        String str;
        try {
            if ((str = socketConnector.read()) != null) {
                if (str.equalsIgnoreCase("echo")) {
                    DDBServerView.getInstance().setText("echo begin");
                    clientEcho();
                    DDBServerView.getInstance().setText("echo end");
                } else if (str.equalsIgnoreCase("sync")) {
                    DDBServerView.getInstance().setText("sync begin");
                    clientSync();
                    DDBServerView.getInstance().setText("synv end");
                } else if (str.equalsIgnoreCase("active")) {
                    DDBServerView.getInstance().setText("active begin");
                    clientActive();
                    DDBServerView.getInstance().setText("active end");
                } else if (str.equalsIgnoreCase("file")) {
                    DDBServerView.getInstance().setText("file begin");
                    clientReciveFile();
                    DDBServerView.getInstance().setText("file end");
                } else if (str.equalsIgnoreCase("object")) {
                    DDBServerView.getInstance().setText("object begin");
//                    clientSendObjcet();
                    this.clientReceiveObject();
                    DDBServerView.getInstance().setText("object end");
                } else if (str.equalsIgnoreCase("objectSQLResult")){
                    DDBServerView.getInstance().setText("objectSQLResult begin");
                    clientSendObjcet();
                    DDBServerView.getInstance().setText("objectSQLResult end");
                }else if (str.equalsIgnoreCase("deactive")) {
                    DDBServerView.getInstance().setText("deactive begin");
                    clientDeactive();
                    DDBServerView.getInstance().setText("deactive end");
                } else if (str.equalsIgnoreCase("disconnect")) {
                    clientDisconnect();
                } else if (str.equalsIgnoreCase(Constant.DDB_IMPORT)) {
                    DDBServerView.getInstance().setText("importTempData");
                    paser.importData("importTempData ./Data/Data.txt", "Temp");
                } else if (str.equalsIgnoreCase("SQLResult")) {
                    DDBServerView.getInstance().setText("SQLResult begin");
                    clientReceiveSQLResult();
                    DDBServerView.getInstance().setText("SQLResult end");
                } else if (str.equalsIgnoreCase("queryWaitResult")) {
                    DDBServerView.getInstance().setText("queryWaitResult begin");
                    clientReceiveSQLReturnResult();
                    DDBServerView.getInstance().setText("queryWaitResult end");
                } else {
                    mainWindow.setText("client error " + str);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
